using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Oops.Xna.Framework.Physics;

namespace Oops.Xna.Framework.Testing.App
{
	public class Example6Screen : ExampleScreen
	{
		// Content.
		private Texture2D planeTexture;
		
		// Drawing helpers.
		private Quadrilateral quad;
		
		public Example6Screen(Game game) : base(game, "Example6") 
		{
			// Drawing helper for the ground.
			this.quad = new Quadrilateral(Vector3.Zero, Vector3.Up, Vector3.Backward, 260.0f, 260.0f, 10, 10);
		}

		#region ExampleScreen Members

		protected override void DrawWorld(Effect effect, EffectParameter world, EffectParameter texture)
		{
			// Draw the ground.
			world.SetValue(Matrix.Identity);
			texture.SetValue(this.planeTexture);
			effect.CommitChanges();
			this.GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList, this.quad.Vertices, 0, 4, this.quad.Indices, 0, 2);
		}

		protected override void Reset()
		{
			// Start with 50 boxes and 150 spheres.
			this.Reset(50, 50);

			// Create the ground plane.  
			CollisionPlane plane = new CollisionPlane();
			plane.Normal = Vector3.UnitY;

			// Create a collision group and add the plane.
			CollisionGroup collisionGroup = new CollisionGroup();
			collisionGroup.CollisionShapes.Add(plane);

			// Add the plane's collision group to the collision system.
			this.physics.CollisionSystem.CollisionGroups.Add(collisionGroup);

			for (int i = 0; i < this.spheres.Count; i += 2)
			{
				PointToPointConstraint constraint = new PointToPointConstraint();

				constraint.RigidBody0 = this.spheres[i].CollisionGroup.RigidBody;
				constraint.RelativePosition0 = Vector3.Right * (this.spheres[i].Radius + 0.7f);

				constraint.RigidBody1 = this.spheres[i + 1].CollisionGroup.RigidBody;
				constraint.RelativePosition1 = Vector3.Left * (this.spheres[i + 1].Radius + 0.7f);

				constraint.Tolerance = 1.0f;
				constraint.Timescale = 5.0f;

				Vector3 position = constraint.RigidBody0.Position + Vector3.Right * (this.spheres[i].Radius + this.spheres[i + 1].Radius + 1.4f);
				constraint.RigidBody1.UpdateTransform(ref position);

				this.physics.Constraints.Add(constraint);
			}

			for (int i = 0; i < this.boxes.Count; i += 2)
			{
				HingeConstraint constraint = new HingeConstraint();

				constraint.RigidBody0 = this.boxes[i].CollisionGroup.RigidBody;
				constraint.RelativePosition0 = Vector3.Right * (this.boxes[i].Extents.X + 0.7f);
				
				constraint.RigidBody1 = this.boxes[i + 1].CollisionGroup.RigidBody;
				constraint.RelativePosition1 = Vector3.Left * (this.boxes[i + 1].Extents.X + 0.7f);

				Vector3 position = constraint.RigidBody0.Position + Vector3.Right * (this.boxes[i].Extents.X + this.boxes[i + 1].Extents.X + 1.4f);
				constraint.RigidBody1.UpdateTransform(ref position);

				this.physics.Constraints.Add(constraint);
			}
		}

		#endregion

		#region DrawableGameComponent Members

		protected override void LoadContent()
		{
			// Load all the used texture resources.
			this.planeTexture = this.Game.GetContent().Load<Texture2D>(@".\Content\Textures\plane");
			
			// Call inherited method.
			base.LoadContent();
		}

		#endregion
	}
}
